using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Framework
{
    /// <summary>
    /// This class provides utility methods for formating text from one format to another.
    /// </summary>
    public static class FormatCodeUtil
    {
        #region ToFormatedKeyValues
        public static IEnumerable<KeyValuePair<string, string>> ToFormatedKeyValues(string key, string value, params FormatCodeType[] formatCodeTypes)
        {
            var result = new List<KeyValuePair<string, string>>();
            
            foreach (var formatCodeType in formatCodeTypes)
            {
                var formatedKey = "{0}~{1}".FormatWith(key, formatCodeType.ToString());
                string formatedValue;

                switch (formatCodeType)
                {
                    case FormatCodeType.Identifier:
                        formatedValue = ToIdentifier(value);
                        break;
                    case FormatCodeType.Word:
                        formatedValue = ToWord(value);
                        break;
                    case FormatCodeType.Variable:
                        formatedValue = ToVariable(value);
                        break;
                    case FormatCodeType.Property:
                        formatedValue = ToProperty(value);
                        break;
                    case FormatCodeType.DotProperty:
                        formatedValue = ToDotProperty(value);
                        break;
                    case FormatCodeType.DashProperty:
                        formatedValue = ToDashProperty(value);
                        break;
                    case FormatCodeType.Const:
                        formatedValue = ToConst(value);
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }

                result.Add(new KeyValuePair<string, string>(formatedKey, formatedValue));    

            }
            
            return result;
        }
        #endregion

        #region ToIdentifier
        /// <summary>
        /// Format a string so that is a proper CSharp identifier.
        /// <p>
        /// No additional formating will be performed.
        /// <br/>
        /// An invalid identifier including null will return null.<br/>
        /// <br/>
        /// <b>Example</b><br/>
        /// Console.WriteLine( FormatCodeUtil.ToIdentifier( " david cruwys 1 " ) );<br/>
        /// Output: "davidcruwys1"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToIdentifier( " #1_# " ) );<br/>
        /// Output: _<br/>
        /// Console.WriteLine( FormatCodeUtil.ToIdentifier( " #1david cruwys 1# " ) );<br/>
        /// Output: davidcruwys1<br/>
        /// Console.WriteLine( FormatCodeUtil.ToIdentifier( " #1# " ) );<br/>
        /// Output: null<br/><br/>
        /// </summary>
        /// <param name="str">String to act on</param>
        /// <returns>String in CSharp identifier format.</returns>
        public static string ToIdentifier(string s)
        {
            if (s == null)
            {
                return null;
            }

            if (s.StartsWith("~"))
            {
                return StrUtil.RightOf(s, 0);
            }

            StringBuilder result = new StringBuilder(s.Length);
            char[] source = s.ToCharArray();
            bool found1st = false;

            for (int i = 0; i < source.Length; i++)
            {
                if (found1st)
                {
                    if (Char.IsLetterOrDigit(source[i]) || source[i] == '_')
                    {
                        result.Append(source[i]);
                    }
                }
                else
                {
                    if (Char.IsLetter(source[i]) || source[i] == '_')
                    {
                        found1st = true;
                        result.Append(source[i]);
                    }

                }
            }
            return (found1st ? result.ToString().Trim() : null);
        }
        #endregion

        #region ToWord
        /// <summary>
        /// <para>
        /// Format a string so that becomes a java identifier with special formating.
        /// Only letters and numbers are retained. All other characters are wiped.
        /// The 1st character in the identifier will be the 1st letter found.
        /// Capital case will be applied so that each word starts with a capital letter,
        /// while all other letters in the word will be in lower case.
        /// If a number is found, it will be treated in the same way as a lowercase letter.
        /// </para>
        /// <para>An invalid identifier including null will return null.</para>
        /// <para><b>Example</b></para>
        /// <para>
        /// Console.WriteLine( FormatCodeUtil.ToWord( " david cruwys 1 " ) );<br/>
        /// Output: "DavidCruwys1"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToWord( " #1_# " ) );<br/>
        /// Output: null<br/>
        /// Console.WriteLine( FormatCodeUtil.ToWord( " #1david2 cruwys 1# " ) );<br/>
        /// Output: David2Cruwys<br/>
        /// Console.WriteLine( FormatCodeUtil.ToWord( " #1david2_cruwys 1# " ) );<br/>
        /// Output: David2Cruwys<br/>
        /// Console.WriteLine( FormatCodeUtil.ToWord( " #1david2cruwys 1# " ) );<br/>
        /// Output: David2cruwys<br/><br/>
        /// <b>Test cases for the following:</b><br/>
        /// </para>
        /// <code>
        /// <ul>
        /// <li> FormatCodeUtil.ToWord( "   %#abc_xyz  nbd "      ).equals( "AbcXyzNbd"    ) );</li>
        /// <li> FormatCodeUtil.ToWord( "   %#1_ab234c_xVIyz 2 "  ).equals( "Ab234cXviyz2"   ) );</li>
        /// <li> FormatCodeUtil.ToWord( " david cruwys 1 "        ).equals( "DavidCruwys1"  ) );</li>
        /// <li> FormatCodeUtil.ToWord( " #1_# " ) == null;</li>
        /// <li> FormatCodeUtil.ToWord( " #1david cruwys 1# "     ).equals( "DavidCruwys1"  ) );</li>
        /// <li> FormatCodeUtil.ToWord( " #1$dAVID cRUWYS __ 1# " ).equals( "DavidCruwys1"  ) );</li>
        /// <li> FormatCodeUtil.ToWord( " #1dAVID$ cRUWYS _1_# "  ).equals( "DavidCruwys1"  ) );</li>
        /// <li> FormatCodeUtil.ToWord( " #1david2 cruwys 1# "    ).equals( "David2Cruwys1"  ) );</li>
        /// <li> FormatCodeUtil.ToWord( " #1david 2cruwys 1# "    ).equals( "David2Cruwys1"  ) );</li>
        /// <li> FormatCodeUtil.ToWord( " #1david2_cruwys 1# "    ).equals( "David2Cruwys1"  ) );</li>
        /// <li> FormatCodeUtil.ToWord( " #1david2cruwys 1# "     ).equals( "David2cruwys1"  ) );</li>
        /// <li> FormatCodeUtil.ToWord( "DavidCruwys1"            ).equals( "DavidCruwys1"  ) );</li>
        /// <li> FormatCodeUtil.ToWord( "davidCruwys1"            ).equals( "DavidCruwys1"  ) );</li>
        /// <li> FormatCodeUtil.ToWord( "Davidcruwys1"            ).equals( "Davidcruwys1"  ) );</li>
        /// <li> FormatCodeUtil.ToWord( " #1# " ) == null;</li>
        /// <li> FormatCodeUtil.ToWord( null ) == null;</li>
        /// </ul>
        /// </code>
        /// </summary>
        /// <param name="str">String to act on</param>
        /// <returns>String in CSharp word format.</returns>
        public static string ToWord(string s)
        {
            if (s == null)
            {
                return null;
            }

            if (s.StartsWith("~"))
            {
                return StrUtil.RightOf(s, 0);
            }

            StringBuilder result = new StringBuilder(s.Length);
            char[] source = s.ToCharArray();
            bool found1st = false;
            bool isNewWord = false;
            bool isLastCharLowerOrDigit = false;

            for (int i = 0; i < source.Length; i++)
            {
                if (found1st)
                {
                    if (Char.IsLetterOrDigit(source[i]))
                    {
                        // If starting a new word and letter found or
                        // if last letter found was a lowercase letter or a digit and
                        // this letter is upper then start a new word.
                        if (
                            (isNewWord && Char.IsLetter(source[i])) ||
                            (isLastCharLowerOrDigit && Char.IsUpper(source[i])))
                        {
                            result.Append(Char.ToUpper(source[i]));
                            // Can never be a new word directly after this letter. (Set isNew & isLower false)
                            isNewWord = false;
                            isLastCharLowerOrDigit = false;
                        }
                        else
                        {
                            result.Append(Char.ToLower(source[i]));
                            // Ensure that when we are setting this value that we set it from the
                            // original source and not the modified value found in result.
                            isLastCharLowerOrDigit = Char.IsLower(source[i]) || Char.IsDigit(source[i]);
                        }
                    }
                    else
                    {
                        // If we did not find a leter or digit then the next letter will
                        // be the start a new word.
                        isNewWord = true;
                    }
                }
                else
                {
                    // We cannot do the proceeding block until we have found a letter
                    if (Char.IsLetter(source[i]))
                    {
                        found1st = true;
                        result.Append(Char.ToUpper(source[i]));
                    }

                }
            }

            return (found1st ? result.ToString().Trim() : null);
        }
        #endregion

        #region ToSeperatedWord
        /// <summary>
        /// Format a string as CSharp.ToWord then seperate each word with a <code>[Seperator]</code>.
        /// <br/>
        /// An invalid identifier including null will return null.<br/>
        /// <br/>
        /// <b>Example</b><br/>
        /// Console.WriteLine( FormatCodeUtil.ToSeperatedWord( "FIRST_NAME", '.' ) );<br/>
        /// Output: "First.Name"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToSeperatedWord( "LAST_NAME", '-' ) );<br/>
        /// Output: "Last-Name"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToSeperatedWord( "Type of Document", ' ' ) );<br/>
        /// Output: "Type Of Document"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToSeperatedWord( " #1# ", "" ) );<br/>
        /// Output: null<br/><br/>
        /// </summary>
        /// <param name="str">String to act on</param>
        /// <param name="seperator"> </param>
        /// <returns>String in CSharp Dot Property format.</returns>
        public static string ToSeperatedWord(string str, char seperator)
        {
            var word = ToWord(str);

            if (word == null)
            {
                return null;
            }

            if (word.StartsWith("~"))
            {
                return StrUtil.RightOf(word, 0);
            }

            var result = new StringBuilder(word.Length + 5);
            var source = word.ToCharArray();

            for (var i = 0; i < source.Length; i++)
            {
                // New word encountered insert a period
                if (i > 0 && Char.IsUpper(source[i]))
                {
                    result.Append(seperator);
                }

                result.Append(source[i]);
            }

            return result.ToString();
        }
        #endregion

        #region ToVariable
        /// <summary>
        /// Format a string as CSharp.ToWord with 1st letter in lowercase.
        /// <p>
        /// Prefix can be "" but if passed this will be prefixed to the result.</p>
        /// <br/>
        /// An invalid identifier including null will return null.<br/>
        /// <br/>
        /// <b>Example</b><br/>
        /// Console.WriteLine( FormatCodeUtil.ToVariable( "FIRST_NAME", "m_" ) );<br/>
        /// Output: "m_firstName"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToVariable( "LAST_NAME", "" ) );<br/>
        /// Output: "lastName"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToVariable( "Type of Document", "prop_" ) );<br/>
        /// Output: "prop_typeOfDocument"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToVariable( " #1# ", "" ) );<br/>
        /// Output: null<br/><br/>
        /// </summary>
        /// <param name="str">String to act on</param>
        /// <param name="str">String prefixed to result</param>
        /// <returns>String in CSharp Property format.</returns>
        public static string ToVariable(string s, string prefix)
        {
            string word = ToWord(s);

            if (word == null)
            {
                return null;
            }

            if (s.StartsWith("~"))
            {
                return StrUtil.RightOf(s, 0);
            }

            return prefix + word.Substring(0, 1).ToLower() + word.Substring(1);
        }

        public static string ToVariable(string s)
        {
            return ToVariable(s, "");
        }
        #endregion

        #region ToProperty
        /// <summary>
        /// Format a string as CSharp.ToWord with 1st letter in lowercase.
        /// <p>
        /// Prefix can be "" but if passed this will be prefixed to the result.
        /// <br/>
        /// An invalid identifier including null will return null.<br/>
        /// <br/>
        /// <b>Example</b><br/>
        /// Console.WriteLine( FormatCodeUtil.ToProperty( "FIRST_NAME", "m_" ) );<br/>
        /// Output: "m_firstName"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToProperty( "LAST_NAME", "" ) );<br/>
        /// Output: "lastName"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToProperty( "Type of Document", "prop_" ) );<br/>
        /// Output: "prop_typeOfDocument"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToProperty( " #1# ", "" ) );<br/>
        /// Output: null<br/><br/>
        /// </summary>
        /// <param name="str">String to act on</param>
        /// <param name="str">String prefixed to result</param>
        /// <returns>String in CSharp Property format.</returns>
        public static string ToProperty(string s, string prefix)
        {
            string word = ToWord(s);

            if (word == null)
            {
                return null;
            }

            if (s.StartsWith("~"))
            {
                return StrUtil.RightOf(s, 0);
            }

            return prefix + word.Substring(0, 1).ToLower() + word.Substring(1);
        }

        public static string ToProperty(string s)
        {
            return ToProperty(s, "");
        }
        #endregion

        #region ToDotProperty
        /// <summary>
        /// Format a string as CSharp.ToWord then seperate each word with a period <code>.</code> and then return all in Lower Case.
        /// <br/>
        /// An invalid identifier including null will return null.<br/>
        /// <br/>
        /// <b>Example</b><br/>
        /// Console.WriteLine( FormatCodeUtil.ToDotProperty( "FIRST_NAME" ) );<br/>
        /// Output: "first.name"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToDotProperty( "LAST_NAME" ) );<br/>
        /// Output: "last.name"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToDotProperty( "Type of Document" ) );<br/>
        /// Output: "type.of.document"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToDotProperty( " #1# ", "" ) );<br/>
        /// Output: null<br/><br/>
        /// </summary>
        /// <param name="str">String to act on</param>
        /// <returns>String in CSharp Dot Property format.</returns>
        public static string ToDotProperty(string str)
        {
            return ToSeperatedProperty(str, '.');
        }
        #endregion

        #region ToDashProperty
        /// <summary>
        /// Format a string as CSharp.ToWord then seperate each word with a period <code>.</code> and then return all in Lower Case.
        /// <br/>
        /// An invalid identifier including null will return null.<br/>
        /// <br/>
        /// <b>Example</b><br/>
        /// Console.WriteLine( FormatCodeUtil.ToDashProperty( "FIRST_NAME" ) );<br/>
        /// Output: "first.name"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToDashProperty( "LAST_NAME" ) );<br/>
        /// Output: "last.name"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToDashProperty( "Type of Document" ) );<br/>
        /// Output: "type.of.document"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToDashProperty( " #1# ", "" ) );<br/>
        /// Output: null<br/><br/>
        /// </summary>
        /// <param name="str">String to act on</param>
        /// <returns>String in CSharp Dot Property format.</returns>
        public static string ToDashProperty(string str)
        {
            return ToSeperatedProperty(str, '-');
        }
        #endregion

        #region ToSeperatedProperty
        /// <summary>
        /// Format a string as CSharp.ToWord then seperate each word with a period <code>[Seperator]</code> and then return all in Lower Case.
        /// <br/>
        /// An invalid identifier including null will return null.<br/>
        /// <br/>
        /// <b>Example</b><br/>
        /// Console.WriteLine( FormatCodeUtil.ToSeperatedProperty( "FIRST_NAME" ) );<br/>
        /// Output: "first.name"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToSeperatedProperty( "LAST_NAME" ) );<br/>
        /// Output: "last.name"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToSeperatedProperty( "Type of Document" ) );<br/>
        /// Output: "type.of.document"<br/>
        /// Console.WriteLine( FormatCodeUtil.ToSeperatedProperty( " #1# ", "" ) );<br/>
        /// Output: null<br/><br/>
        /// </summary>
        /// <param name="str">String to act on</param>
        /// <param name="seperator"> </param>
        /// <returns>String in CSharp Dot Property format.</returns>
        public static string ToSeperatedProperty(string str, char seperator)
        {
            string word = ToWord(str);

            if (word == null)
            {
                return null;
            }

            if (word.StartsWith("~"))
            {
                return StrUtil.RightOf(word, 0);
            }

            var result = new StringBuilder(word.Length + 5);
            var source = word.ToCharArray();

            for (var i = 0; i < source.Length; i++)
            {
                // New word encountered insert a period
                if (i > 0 && Char.IsUpper(source[i]))
                {
                    result.Append(seperator);
                }

                result.Append(Char.ToLower(source[i]));
            }

            return result.ToString();
        }
        #endregion

        #region ToConst
        /// <summary>
        /// Standard constant field is every word in uppercase with underscores to seperate words.
        /// <br/>
        /// An invalid identifier including null will return null.<br/>
        /// <br/>
        /// <b>Example</b><br/>
        /// Console.WriteLine( FormatCodeUtil.toJavaConst( "FirstName" ) );<br/>
        /// Output: "FIRST_NAME"<br/>
        /// Console.WriteLine( FormatCodeUtil.toJavaConst( "3%Last name" ) );<br/>
        /// Output: "LAST_NAME"<br/>
        /// Console.WriteLine( FormatCodeUtil.toJavaConst( "Type of document1" ) );<br/>
        /// Output: "TYPE_OF_DOCUMENT1"<br/>
        /// Console.WriteLine( FormatCodeUtil.toJavaConst( " #1# ", "" ) );<br/>
        /// Output: null<br/><br/>
        /// </summary>
        /// <param name="str">String to act on</param>
        /// <returns>String in Constant format.</returns>
        public static string ToConst(string s)
        {
            string word = ToWord(s);

            if (word == null)
            {
                return null;
            }

            if (s.StartsWith("~"))
            {  // Don't use word as it has stripped the '~' away.
                return StrUtil.RightOf(s, 0);
            }

            StringBuilder result = new StringBuilder(word.Length + 5);
            char[] source = word.ToCharArray();

            for (int i = 0; i < source.Length; i++)
            {
                // New word encountered insert a period
                if (i > 0 && Char.IsUpper(source[i]))
                {
                    result.Append('_');
                }

                result.Append(Char.ToUpper(source[i]));
            }

            return result.ToString();
        }
        #endregion

        #region ToType
        /// <summary>
        /// Format Data Type.
        /// </summary>
        /// <param name="type">Data type</param>
        /// <param name="defaultType">Use if type is invalid</param>
        /// <returns></returns>
        public static string ToType(string type, string defaultType)
        {
            if (Is.EmptyString(type))
            {
                return ToWord(defaultType);
            }

            return ToType(type);
        }

        /// <summary>
        /// Format Data Type.
        /// </summary>
        /// <param name="type">Data type</param>
        /// <returns></returns>
        public static string ToType(string type)
        {
            if (Is.EmptyString(type))
            {
                return "string";
            }

            if (type.StartsWith("~"))
            {
                return StrUtil.RightOf(type, 0);
            }

            string t = ("|" + type.ToLower().Trim() + "|");

            if ("|bool|int|decimal|double|long|string|object|".IndexOf(t) == -1)
            {  // Some Unknown Type
                return ToWord(type);
            }

            return type;
        }
        #endregion

        #region ToTypeObject
        /// <summary>
        /// Format Data Type.
        /// </summary>
        /// <param name="type">Data type</param>
        /// <param name="defaultType">Use if type is invalid</param>
        /// <returns></returns>
        public static string ToTypeObject(string type, string defaultType)
        {
            if (Is.EmptyString(type))
            {
                return ToWord(defaultType);
            }

            return ToTypeObject(type);
        }

        /// <summary>
        /// Format Data Type.
        /// </summary>
        /// <param name="type">Data type</param>
        /// <returns></returns>
        public static string ToTypeObject(string type)
        {
            if (Is.EmptyString(type))
            {
                return "System.String";
            }

            if (type.StartsWith("~"))
            {
                return StrUtil.RightOf(type, 0);
            }

            string t = ("|" + type.ToLower().Trim() + "|");

            if ("|bool|int|int32|decimal|double|long|string|object|".IndexOf(t) == -1)
            {  // Some Unknown Type
                return ToWord(type);
            }

            switch (type.ToLower().Trim())
            {
                case "string": return "System.String";
                case "bool": return "System.Boolean";
                case "int": return "System.Int32";
                case "int32": return "System.Int32";
                case "long": return "System.Int64";
                case "decimal": return "System.Decimal";
                case "double": return "System.Double";
                case "object": return "System.Object";
            }

            return type;
        }
        #endregion

        #region ToModifier
        public static string ToModifier(string modifierTypes)
        {
            return ToModifier(BuildModifierTypes(modifierTypes), FormatModifierType.Public.ToString().ToLower());
        }

        public static string ToModifier(string modifierTypes, string defaultModifier)
        {
            return ToModifier(BuildModifierTypes(modifierTypes), defaultModifier);
        }

        public static string ToModifier(string[] modifierTypes)
        {
            return ToModifier(BuildModifierTypes(modifierTypes), FormatModifierType.Public.ToString().ToLower());
        }

        public static string ToModifier(string[] modifierTypes, string defaultModifier)
        {
            return ToModifier(BuildModifierTypes(modifierTypes), defaultModifier);
        }

        public static string ToModifier(FormatModifierType[] modifierTypes, string defaultModifier)
        {
            if (modifierTypes == null || modifierTypes.Length == 0)
            {
                return defaultModifier;
            }

            StringBuilder result = new StringBuilder();

            for (int i = 0; i < modifierTypes.Length; i++)
            {
                if (i > 0)
                {
                    result.Append(' ');
                }
                result.Append(modifierTypes[i].ToString().ToLower());
            }

            return result.ToString();
        }
        #endregion

        #region BuildModifierTypes
        public static FormatModifierType[] BuildModifierTypes(string modifierTypes)
        {
            return BuildModifierTypes(DelimitedUtil.Split(modifierTypes, ' '));
        }

        public static FormatModifierType[] BuildModifierTypes(string[] modifierTypes)
        {
            if (Is.EmptyArray(modifierTypes))
            {
                return new FormatModifierType[0];
            }

            FormatModifierType[] result = new FormatModifierType[modifierTypes.Length];

            for (int i = 0; i < modifierTypes.Length; i++)
            {
                result[i] = ((FormatModifierType)EnumUtil.Parse(typeof(FormatModifierType), modifierTypes[i], FormatModifierType.Unknown));
            }

            Array.Sort(result, new ModifierTypeComparer());

            return result;
        }
        #endregion

        #region ToNaturalWord
        /// <summary>
        /// Format a FormatCodeUtil string so it is broken up with spaces between individual words
        /// <br/>
        /// An invalid identifier including null will return null.<br/>
        /// <br/>
        /// <b>Example</b><br/>
        /// Console.WriteLine( TextStyle.toNaturalWord( "david Cruwys" ) );<br/>
        /// Output: "David Cruwys"<br/>
        /// Console.WriteLine( TextStyle.toNaturalWord( "setLastName" ) );<br/>
        /// Output: "Set Last Name"<br/>
        /// Console.WriteLine( TextStyle.toNaturalWord( "getRequestURL" ) );<br/>
        /// Output: "Get Request Url"<br/>
        /// Output: null<br/><br/>
        /// </summary>
        /// <param name="str">String to act on</param>
        /// <returns>String in sentence case.</returns>
        public static string ToNaturalWord(string s)
        {
            string word = ToWord(s);

            if (word == null)
            {
                return null;
            }

            if (s.StartsWith("~"))
            {
                return StrUtil.RightOf(s, 0);
            }

            StringBuilder result = new StringBuilder(word.Length + 5);
            char[] source = word.ToCharArray();

            for (int i = 0; i < source.Length; i++)
            {
                if (i > 0 && (Char.IsUpper(source[i]) || Char.IsDigit(source[i])))
                {
                    result.Append(' ');
                }

                result.Append(source[i]);
            }

            return result.ToString();
        }
        #endregion

        #region DefaultAssignment
        public static string DefaultAssignment(string type)
        {
            return DefaultAssignment(type, "null");
        }

        public static string DefaultAssignment(string type, string defaultAssignment)
        {
            if (Is.EmptyString(defaultAssignment))
            {
                if (Is.EmptyString(type))
                {
                    return " = null;";
                }

                string t = ("|" + type.ToLower().Trim() + "|");

                if (t == "|datetime|")
                {
                    return " = DateUtil.MinValue;";
                }
                else if (t == "|bool|")
                {
                    return " = false;";
                }
                else if ("|int|long|decimal|double|".IndexOf(t) == -1)
                {
                    return " = null;";
                }
                else
                {
                    return ";";
                }
            }

            if (Is.EqualString(defaultAssignment, "default"))
            {
                return ";";
            }

            return " = " + defaultAssignment + ";";
        }

        public static string DefaultAssignmentInstance(string type)
        {
            return " = new " + type + "();";
        }
        #endregion

        #region DefaultEmptyValue
        public static string DefaultEmptyValue(string type)
        {
            string t = ("|" + type.ToLower().Trim() + "|");

            if (t == "|string|")
            {
                return "string.Empty";
            }
            if (t == "|datetime|")
            {
                return "DateUtil.MinValue";
            }
            else if (t == "|bool|")
            {
                return "false";
            }
            else if ("|int|long|".IndexOf(t) != -1)
            {
                return "0";
            }
            else if ("|double|".IndexOf(t) != -1)
            {
                return "0.0M";
            }
            else if ("|decimal|".IndexOf(t) != -1)
            {
                return "0.0M";
            }

            return "null";
        }
        #endregion

        #region DefaultAssignmentEmptyValue
        public static string DefaultAssignmentEmptyValue(string type)
        {
            return " = " + DefaultEmptyValue(type) +";";
        }
        #endregion

        #region ModifierTypeComparer (Class)
        public class ModifierTypeComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                return ((FormatModifierType)x).CompareTo((FormatModifierType)y);
            }
        }
        #endregion

        #region DbTypeToDotNetType
        public static string DbTypeToDotNetType(string dataType)
        {
            switch (dataType.ToLower())
            {
                case "int":
                    return "int";
                case "bit":
                    return "bool";
                case "float":
                    return "decimal";
                case "bigint":
                    return "long";
                case "datetime":
                    return "DateTime";
                case "xml":
                    return "XElement";
                case "nvarchar":
                case "text":
                case "ntext":
                    return "string";
                default:
                    _.P(" ******************** Note: Unknown data type: " + dataType);
                    return "string";
            }
        }
        #endregion

        #region DotNetTypeToDbType
        public static string DotNetTypeToDbType(string dataType)
        {
            switch (dataType.ToLower())
            {
                case "int":
                    return "int";
                case "bool":
                    return "Bit";
                case "double":
                    return "Float";
                case "long":
                    return "BigInt";
                case "datetime":
                    return "DateTime";
                case "xelement":
                    return "xml";
                case "string":
                    return "nvarchar";
                default:
                    _.P(" ******************** Note: Unknown data type: " + dataType);
                    return "nvarchar";
            }
        }
        #endregion

        #region HumanTypeToDotNetType
        /// <summary>
        /// Convert types (readable by humans) to .NET type
        /// </summary>
        /// <example>
        /// Boolean
        /// Decimal
        /// String
        /// Integer
        /// </example>
        /// <param name="dataType">Type of the data.</param>
        /// <returns></returns>
        public static string HumanTypeToDotNetType(string dataType)
        {
            switch (dataType.ToLower())
            {
                case "int":
                case "integer":
                    return "int";

                case "bit":
                case "bool":
                case "boolean":
                    return "bool";

                case "float":
                case "decimal":
                    return "double";

                case "bigint":
                    return "long";

                case "date":
                case "datetime":
                    return "DateTime";

                case "xml":
                    return "XElement";

                case "string":
                case "nvarchar":
                case "text":
                case "ntext":
                    return "string";
                default:
                    _.P(" ******************** Note: Unknown data type: " + dataType);
                    return "string";
            }
        }
        #endregion

        #region DotNetTypeSampleValue
        public static string DotNetTypeSampleValue(string dataType)
        {
            switch (dataType.ToLower())
            {
                case "int":
                    return "0";
                case "bool":
                    return "false";
                case "double":
                    return "0.0";
                case "datetime":
                    return "DateTime.Now";
                case "string":
                    return "string.Empty";
                default:
                    _.P(" ******************** Note: Unknown data type sample value: " + dataType);
                    return "null";
            }
        }
        #endregion
    }

    public enum FormatCodeType
    {
        Identifier,

        Word,

        Variable,

        Property,

        DotProperty,

        DashProperty,

        Const
    }
}